package com.shiwaixiangcun.monitor.service.impl;

import com.rabbit.spring.data.search.SearchOperator;
import com.rabbit.spring.data.search.Searchable;
import com.rabbit.spring.data.search.filter.SearchFilter;
import com.rabbit.spring.data.search.filter.SearchFilterHelper;
import com.shiwaixiangcun.core.exceptions.MonkeyException;
import com.shiwaixiangcun.core.plugin.dto.MonkeyDto;
import com.shiwaixiangcun.core.plugin.report.pdf.PdfData;
import com.shiwaixiangcun.core.service.BaseServiceImpl;
import com.shiwaixiangcun.core.utils.MonkeyUtils;
import com.shiwaixiangcun.monitor.domain.*;
import com.shiwaixiangcun.monitor.dto.*;
import com.shiwaixiangcun.monitor.enums.PriorityLevel;
import com.shiwaixiangcun.monitor.enums.WorkOrderServiceType;
import com.shiwaixiangcun.monitor.enums.WorkOrderStatus;
import com.shiwaixiangcun.monitor.repository.EarlyWarningRepository;
import com.shiwaixiangcun.monitor.repository.WorkOrderCategoryRepository;
import com.shiwaixiangcun.monitor.repository.WorkOrderRepository;
import com.shiwaixiangcun.monitor.security.SecurityUtils;
import com.shiwaixiangcun.monitor.service.*;
import com.shiwaixiangcun.monitor.utils.NumberGenerator;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2017-11-23.
 */

@Service
public class WorkOrderServiceImpl extends BaseServiceImpl<WorkOrder, Long> implements WorkOrderService {
    @Autowired
    private WorkOrderRepository workOrderRepository;

    @Autowired
    private WorkOrderCategoryRepository workOrderCategoryRepository;
    @Autowired
    private UserService userService;
    @Autowired
    private WorkOrderServiceRecordService workOrderServiceRecordService;
    @Autowired
    private WorkOrderQualityAllotRuleService workOrderQualityAllotRuleService;
    @Autowired
    private WorkOrderQualityRecordService workOrderQualityRecordService;
    @Autowired
    private NumberGenerator numberGenerator;
    @Autowired
    private EarlyWarningRepository earlyWarningRepository;

    @Override
    public void addWorkOrder(MonkeyDto monkeyDto) {
        WorkOrder workOrder = initWorkOrder(monkeyDto);
        workOrderRepository.save(workOrder);

        String content = SecurityUtils.getCurrentUser().getName() + "分配给" + workOrder.getUser().getName();
        workOrderServiceRecordService.createServiceRecord(workOrder, WorkOrderServiceType.Accepted, content);
    }

    @Override
    public WorkOrderListDto getWorkOrderList(Pageable pageable, WorkOrderQueryDto workOrderQueryDto) {
        WorkOrderListDto workOrderListDto = new WorkOrderListDto();
        User currentUser = SecurityUtils.getCurrentUser();
        Searchable searchable1 = Searchable.newSearchable();
        searchable1.addSearchFilter("user", SearchOperator.eq, currentUser);
        List<WorkOrder> workOrderList = workOrderRepository.findAll(searchable1).getContent();
        workOrderListDto.setAcceptedWork(workOrderList.size());

        Searchable searchable2 = Searchable.newSearchable();
        searchable2.addSearchFilter("createdBy", SearchOperator.eq, currentUser.getId());
        List<WorkOrder> workOrderList2 = workOrderRepository.findAll(searchable2).getContent();
        workOrderListDto.setCommitedWork(workOrderList2.size());

        Searchable searchable3 = Searchable.newSearchable();
        searchable3.addSearchFilter("timeout", SearchOperator.eq, true);
        List<WorkOrder> workOrderList3 = workOrderRepository.findAll(searchable3).getContent();
        workOrderListDto.setTimeoutWork(workOrderList3.size());

        Searchable searchable4 = Searchable.newSearchable();
        List<WorkOrder> workOrderList4 = workOrderRepository.findAll(searchable4).getContent();
        workOrderListDto.setAllWork(workOrderList4.size());


        String chose = workOrderQueryDto.getChose();
        Searchable searchable = Searchable.newSearchable();
        searchable.addSort(Sort.Direction.DESC, "createTime");
        int pageIndex = pageable.getPageNumber() * pageable.getPageSize();
        int pageSize = pageable.getPageSize();

        //我受理的
        if (WorkOrderQueryDto.WORKORDER_ACCEPTED.equals(chose)) {
            searchable.addSearchFilter("user", SearchOperator.eq, currentUser);
        }
        //我创建的
        if (WorkOrderQueryDto.WORKORDER_COMMITED.equals(chose)) {
            searchable.addSearchFilter("createdBy", SearchOperator.eq, currentUser.getId());
        }
        //超时的
        if (WorkOrderQueryDto.WORKORDER_TIMEOUT.equals(chose)) {
            searchable.addSearchFilter("timeout", SearchOperator.eq, true);
        }
        //全部工单
        if (WorkOrderQueryDto.WORKORDER_ALL.equals(chose)) {
            if (MonkeyUtils.isNotEmpty(workOrderQueryDto.getSearchKeyWord())) {
                SearchFilter f1 = SearchFilterHelper.newCondition("number", SearchOperator.like, "%" + workOrderQueryDto.getSearchKeyWord() + "%");
                SearchFilter f2 = SearchFilterHelper.newCondition("title", SearchOperator.like, "%" + workOrderQueryDto.getSearchKeyWord() + "%");
                searchable.or(f1, f2);
            }
            if (MonkeyUtils.isNotEmpty(workOrderQueryDto.getPriorityLevel())) {
                searchable.addSearchFilter("priorityLevel", SearchOperator.eq, workOrderQueryDto.getPriorityLevel());
            }
            if (MonkeyUtils.isNotEmpty(workOrderQueryDto.getWorkOrderStatus())) {
                searchable.addSearchFilter("status", SearchOperator.eq, workOrderQueryDto.getWorkOrderStatus());
            }

            if (MonkeyUtils.isNotEmpty(workOrderQueryDto.getCategoryId())) {
                WorkOrderCategory workOrderCategory = workOrderCategoryRepository.findOne(workOrderQueryDto.getCategoryId());
                searchable.addSearchFilter("category", SearchOperator.eq, workOrderCategory);
            }
        }
        List<WorkOrder> orderPage = workOrderRepository.findAll(searchable).getContent();
        List<WorkOrderDto> workOrderDtoList = buildPageWorkOrderDto(orderPage);
        if (WorkOrderQueryDto.WORKORDER_ALL.equals(chose)) {
            workOrderListDto.setAllWork(orderPage.size());
        }
        if (MonkeyUtils.isNotEmpty(orderPage)) {
            int total = orderPage.size();
            List<WorkOrderDto> orderDtoList = limitList(pageIndex, pageSize, total, workOrderDtoList);
            Page<WorkOrderDto> workOrderDtos = new PageImpl<>(orderDtoList, pageable, total);
            workOrderListDto.setWorkOrderDtos(workOrderDtos);
            return workOrderListDto;
        }
        workOrderListDto.setWorkOrderDtos(new PageImpl<WorkOrderDto>(workOrderDtoList, pageable, 0));
        return workOrderListDto;
    }

    @Override
    public String findCurrentMaxNumber() {
        Long organizationId = SecurityUtils.getCurrentUser().getOrganizationId();
        return workOrderRepository.findNumberByCompanyId(organizationId);
    }

    @Override
    public void handle(Long workOrderId, String content) { // 回复
        WorkOrder workOrder = findOne(workOrderId);
        if (MonkeyUtils.isEmpty(workOrder)) {
            throw new MonkeyException("该工单不存在");
        }
        workOrderServiceRecordService.createServiceRecord(workOrder, WorkOrderServiceType.Reply, content);
    }

    @Override
    public void handle(Long workOrderId, Long userId) { // 转交
        WorkOrder workOrder = doTransfer(workOrderId, userId);
        String content = SecurityUtils.getCurrentUser().getName() + "转交给了" + workOrder.getUser().getName();
        workOrderServiceRecordService.createServiceRecord(workOrder, WorkOrderServiceType.Transfer, content);
    }

    @Override
    public void handle(Long workOrderId) { // 完结
        WorkOrder workOrder = doFinished(workOrderId);
        workOrderServiceRecordService.createServiceRecord(workOrder, WorkOrderServiceType.Finish, "完结了工单");
        createQualityRecordByRule(workOrder);
    }

    @Override
    public WorkOrderDetailDto getDetail(Long id) {
        WorkOrder workOrder = findOne(id);
        WorkOrderDetailDto detailDto = buildDetailDto(workOrder);
        return detailDto;
    }

    private WorkOrderEarlyWarningDetailDto dealWithEarlyWarningDetail(WorkOrder workOrder) {
        EarlyWarning warning = earlyWarningRepository.findByWorkOrder(workOrder);
        if (MonkeyUtils.isNotEmpty(warning)) {
            return buildEarlyWarningDetailDto(warning);
        }
        return null;
    }

    private WorkOrderEarlyWarningDetailDto buildEarlyWarningDetailDto(EarlyWarning warning) {
        WorkOrderEarlyWarningDetailDto earlyWarningDetailDto = new WorkOrderEarlyWarningDetailDto();

        String customer = buildEarlyWarningContentCustomer(warning);
        if(MonkeyUtils.isNotEmpty(customer)) {
            earlyWarningDetailDto.setCustomer(customer);
        }


        for (WarningContent warningContent : warning.getWarningContents()) {
            earlyWarningDetailDto.addContent(warningContent.getContent(), warningContent.getWaringTime());
        }

        earlyWarningDetailDto.setOther(warning.getWorkOrder().getContent());
        return earlyWarningDetailDto;
    }

    private String buildEarlyWarningContentCustomer(EarlyWarning warning) {
        String customer = "";
        if (!warning.getBeeper()) {
            customer += warning.getName();
            if (MonkeyUtils.isNotEmpty(warning.getPhone())) {
                customer += "," + warning.getPhone();
            }
            if (MonkeyUtils.isNotEmpty(warning.getAge())) {
                customer += "," + warning.getAge() + "岁";
            }
            if (MonkeyUtils.isNotEmpty(warning.getSex())) {
                customer += "," + warning.getSex().getLabel();
            }
        }
        return customer;
    }

    @Override
    public PdfData print(Long workOrderId) {
        PdfData pdfData = new PdfData();
        WorkOrder workOrder = findOne(workOrderId);
        WorkOrderDetailDto detail = getDetail(workOrderId);
        if (MonkeyUtils.isEmpty(workOrder)) {
            throw new MonkeyException("error", "数据不存在");
        }

        pdfData.addParameter("workOrderRise", "监控中心服务工单");
        pdfData.addParameter("number", workOrder.getNumber());
        pdfData.addParameter("level", workOrder.getPriorityLevel().getLabel());
        //pdfData.addParameter("sponsor", workOrder.getUser().getName() + " " + workOrder.getUser().getPhone());
        pdfData.addParameter("date", MonkeyUtils.toDateText(workOrder.getCreateTime(), MonkeyUtils.DEFAULT_DATE_TIME_FORMAT));
        pdfData.addParameter("type", workOrder.getCategory().getName());
        pdfData.addParameter("receiveStaff", workOrder.getUser().getName() + " " + workOrder.getUser().getPhone());
        pdfData.addParameter("status", workOrder.getStatus().getLabel());
        pdfData.addParameter("title", workOrder.getTitle());

        String content = buildContent(detail);
        pdfData.addParameter("content", content);

        pdfData.setReportURL("classpath:report/pdf/workorder.jrxml");
        pdfData.setDownloadFileName("工单.pdf");
        return pdfData;
    }

    @Override
    public Map getWorkOrderToFigure() {
        Integer total = workOrderRepository.getWorkOrderToFigure();
        Map map = new HashMap();
        map.put("total", total);
        return map;
    }

    private String buildContent(WorkOrderDetailDto detailDto) {
        StringBuffer content = new StringBuffer("");
        if (MonkeyUtils.isEmpty(detailDto.getContent())) {
            content.append("该工单未填写内容");
        } else {
            WorkOrderEarlyWarningDetailDto warning = detailDto.getEarlyWarningDetail();
            if (MonkeyUtils.isNotEmpty(warning)) {
                if (MonkeyUtils.isNotEmpty(warning.getCustomer())) {
                    content.append("客户信息：\n");
                    content.append(warning.getCustomer() + "\n");
                }
                content.append("预警信息：\n");
                for (EarlyWarningDetailContentDto contentDto : warning.getContent()) {
                    content.append(contentDto.getText() + " ");
                    content.append(MonkeyUtils.toDateText(contentDto.getDate(), MonkeyUtils.DATE_TIME_FORMAT) + "\n");
                }
                content.append("其他情况：\n");
                content.append(warning.getOther());
            } else {
                content.append(detailDto.getContent());
            }
        }
        return content.toString();
    }

    private WorkOrderDetailDto buildDetailDto(WorkOrder workOrder) {
        WorkOrderDetailDto detailDto = new WorkOrderDetailDto();
        WorkOrderDto dto = toDto(workOrder);
        BeanUtils.copyProperties(dto, detailDto);
        detailDto.setContent(workOrder.getContent());
        detailDto.setRecord(workOrderServiceRecordService.getServiceRecordList(workOrder));
        detailDto.setEarlyWarningDetail(dealWithEarlyWarningDetail(workOrder));
        detailDto.setUserId(workOrder.getUser().getId());
        return detailDto;
    }

    private WorkOrder doTransfer(Long workOrderId, Long userId) {
        WorkOrder workOrder = findOne(workOrderId);
        if (MonkeyUtils.isEmpty(workOrder)) {
            throw new MonkeyException("该工单不存在");
        }
        User user = userService.findOne(userId);
        if (MonkeyUtils.isEmpty(user)) {
            throw new MonkeyException("该转交人不存在");
        }
        workOrder.setUser(user);
        return workOrderRepository.save(workOrder);
    }

    private WorkOrder doFinished(Long workOrderId) {
        WorkOrder workOrder = findOne(workOrderId);
        if (MonkeyUtils.isEmpty(workOrder)) {
            throw new MonkeyException("该工单不存在");
        }
        workOrder.setStatus(WorkOrderStatus.Finished);
        return save(workOrder);
    }

    private void createQualityRecordByRule(WorkOrder workOrder) {
        WorkOrderCategory category = workOrder.getCategory();
        User user = findQualityUser(category);
        if (MonkeyUtils.isNotEmpty(user)) {
            workOrderQualityRecordService.createQualityRecord(workOrder, user);
        }
    }

    private User findQualityUser(WorkOrderCategory category) {
        if (MonkeyUtils.isEmpty(category)) {
            return null;
        }
        WorkOrderQualityAllotRule rule = workOrderQualityAllotRuleService.getUsableRule(category);
        if (MonkeyUtils.isNotEmpty(rule)) {
            return rule.getUser();
        } else {
            category = workOrderCategoryRepository.findOne(category.getParentId());
            return findQualityUser(category);
        }
    }

    private List<WorkOrderDto> buildPageWorkOrderDto(List<WorkOrder> orderPage) {
        List<WorkOrderDto> workOrderDtos = new ArrayList<>();
        for (WorkOrder workOrder : orderPage) {
            workOrderDtos.add(toDto(workOrder));
        }
        return workOrderDtos;
    }

    private WorkOrderDto toDto(WorkOrder workOrder) {
        WorkOrderDto workOrderDto = new WorkOrderDto();
        workOrderDto.setNumber(workOrder.getNumber());
        workOrderDto.setTitle(workOrder.getTitle());
        workOrderDto.setStatus(workOrder.getStatus().getLabel());
        workOrderDto.setCategory(workOrder.getCategory().getName());
        workOrderDto.setCreateTime(workOrder.getCreateTime());
        workOrderDto.setPriorityLevel(workOrder.getPriorityLevel().getLabel());
        workOrderDto.setUserName(workOrder.getUser().getName());
        workOrderDto.setWorkOrderId(workOrder.getId());
        return workOrderDto;
    }

    private <M> List<M> limitList(int pageIndex, int pageSize, int total, List<M> data) {
        // 根据 条件获取到 分页的结构和数据
        List<M> list;
        if (total < pageSize) {
            list = data.subList(pageIndex, total);
        } else {
            int toSize = pageIndex + pageSize;
            if (toSize > total) {
                toSize = pageIndex + total % pageSize;
            }
            list = data.subList(pageIndex, toSize);
        }
        return list;
    }

    private WorkOrder initWorkOrder(MonkeyDto monkeyDto) {
        WorkOrder workOrder = new WorkOrder();
        String number = numberGenerator.generateWorkOrderNumber();
        workOrder.setNumber(number);
        workOrder.setStatus(WorkOrderStatus.Accepted);
        WorkOrderCategory Category = workOrderCategoryRepository.findOne(monkeyDto.getLong("categoryId"));
        workOrder.setCategory(Category);
        workOrder.setContent(monkeyDto.getString("content"));
        workOrder.setTitle(monkeyDto.getString("title"));
        workOrder.setTimeout(false);
        Long staffId = monkeyDto.getLong("staffId");
        User user = userService.findOne(staffId);
        workOrder.setUser(user);
        workOrder.setPriorityLevel(PriorityLevel.valueOf(monkeyDto.getString("priorityLevel")));
        return workOrder;
    }
}
